package com.ifp.core.connector;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.collections.map.HashedMap;
import org.apache.commons.lang3.StringUtils;

import com.ifp.adapter.common.AdapterCanstants;
import com.ifp.core.data.DataElement;
import com.ifp.core.exception.BaseException;
import com.ifp.core.log.Trace;
import com.ifp.core.util.SpringContextsUtil;
import com.ifp.gateway.bean.MessageDefine;
import com.ifp.gateway.bean.MsgField;
import com.ifp.gateway.formatter.IFormatter;
import com.ifp.opengate.boot.constants.Constants;
import com.ifp.opengate.boot.utils.HeaderToBodyUtil;
import com.ifp.opengate.boot.utils.Xml2JsonUtil;

import net.sf.json.JSONObject;

/**
 * @className: TCPIFP2ServiceConnector
 * @description: TCP短链接连接器
 * @author: 码农7号
 * @email: guanhh1@belink.com
 * @create: 2019-07-10 09:29
 **/
public class TCPIFP2ServiceConnector extends AbstractConnector {
    private static final String[] REQSTRS = {"termnId", "userId", "userCertLevel", "pageSize", "offset", "behavCode"};
    private static final String[] REQ_BODYS = {"userId", "userCertLevel", "behavCode", "pageSize", "offset"};

    private String getDateStrByPartten(Date date, String formate) {
        SimpleDateFormat sm = new SimpleDateFormat(formate);
        return sm.format(date);
    }

    /**
     * 处理交互平台公共报文头固定值数据
     */
    private void handleCommonHead(Map<String, Object> reqHeader, String requestIp) {
        reqHeader.put(Constants.CHNLID, "99");// 固定值
        reqHeader.put(Constants.APPID, Constants.OPEN);// 固定值
        Date date = new Date();
        reqHeader.put(Constants.REQTIME, date.getTime());// 1592533992147
        reqHeader.put(Constants.REQUESTTIMESS, getDateStrByPartten(date, "yyyy-MM-dd HH.mm.ss.SSS"));// yyyy-MM-dd
                                                                                                     // HH.mm.ss.SSS
        String date8Str = getDateStrByPartten(date, "yyyyMMdd");
        reqHeader.put(Constants.REQUESTDAY, date8Str);// yyyyMMdd
        reqHeader.put(Constants.REQUESTTIME, getDateStrByPartten(date, "yyyyMMddHHmmss"));// yyyyMMddHHmmss
        reqHeader.put(Constants.CHANNELID, "336");// 固定值
        reqHeader.put(Constants.CLIENTTYP, "200011");// 固定值
        reqHeader.put(Constants.CHNLCD, "0103");// 固定值
        reqHeader.put(Constants.SRVSYSCD, "053");// 固定值
        reqHeader.put(Constants.HOSTIP, requestIp);// hostIp
        reqHeader.put(Constants.REQIP, requestIp);// reqIP
        String date6Str = getDateStrByPartten(date, "yyMMdd");
        String snowStr = String.valueOf(SNOWFLAKE.nextId());
        reqHeader.put(Constants.BIZTRACKNO, Constants.OPEN + date6Str + snowStr.substring(8));// bizTrackNo
        reqHeader.put(Constants.REQSEQNO, Constants.OPEN + date6Str + snowStr.substring(8));// reqSeqNo
        reqHeader.put(Constants.BZTRANSID, Constants.BZTRANSID_VALUE + date8Str + snowStr.substring(6));// bzTransId
        reqHeader.put(Constants.TRANSID, Constants.TRANSID_VALUE + date8Str + snowStr.substring(3));// transId
    }

    @Override
    public String sendAndReceive(String actionName, String path, Object o) throws Exception {
        Map<String, Object> dataMap = (Map<String, Object>)o;
        Map<String, Object> reqMap = new HashedMap();
        Map<String, Object> reqHeader = new HashedMap();
        Map<String, Object> reqBody = new HashedMap();
        Map<String, Object> headerMap = (Map<String, Object>)dataMap.get(AdapterCanstants.HEADER);
        Map<String, Object> bodyMap = (Map<String, Object>)dataMap.get(AdapterCanstants.BODY);
        for (String key : REQSTRS) {
            reqHeader.put(key, headerMap.get(key));
        }
        for (String key : REQ_BODYS) {
            if (StringUtils.isNotBlank((String)bodyMap.get(key))) {
                reqHeader.put(key, bodyMap.get(key));
                bodyMap.remove(key);
            }
        }

        handleCommonHead(reqHeader, (String)dataMap.get(Constants.REQUEST_IP));
        String serviceId = (String)headerMap.get("consumerId");
        reqHeader.put(Constants.SERVCID, serviceId);
        reqHeader.put(Constants.SERVICECODE, serviceId);

        reqMap.put(AdapterCanstants.HEADER, reqHeader);
        reqMap.put(AdapterCanstants.BODY, bodyMap);
        // 3.发送数据
        Socket socket = null;
        OutputStream outputStream = null;
        InputStream inputStream = null;
        StringBuilder sb = new StringBuilder();
        try {
            // 建立TCP连接
            socket = new Socket(getIp(), Integer.parseInt(getPort()));
            // 写入数据
            outputStream = socket.getOutputStream();
            String reqStr = Xml2JsonUtil.jsonToSocketXml(JSONObject.fromObject(reqMap), serviceId);
            int length2 = reqStr.getBytes().length + 8;
            String lengthStr = String.format("%08d", length2);
            reqStr = lengthStr + reqStr;
            Trace.log(Trace.MODULE_COMMON, Trace.LEVEL_INFO, "this request xml is {}", reqStr);
            outputStream.write(reqStr.getBytes("UTF-8"));
            // 获取响应
            inputStream = socket.getInputStream();
            byte[] bytes = new byte[8];
            inputStream.read(bytes);
            StringBuilder resAll = new StringBuilder(); // 记录完整返回报文
            String length = new String(bytes, "UTF-8").trim(); // 读取前8位长度
            resAll.append(length);
            // length = length.split("=")[1]; // 获取报文长度
            bytes = new byte[Integer.parseInt(length)]; // 读取剩余的报文
            inputStream.read(bytes);
            sb.append(new String(bytes, "UTF-8").trim());
            resAll.append(sb.toString());
            Trace.log(Trace.MODULE_COMMON, Trace.LEVEL_INFO, "this response xml is {}", resAll.toString());
        } catch (UnknownHostException e1) {
            Trace.log(Trace.MODULE_COMMON, Trace.LEVEL_INFO, " create connect faild ");
            throw new BaseException("create connect faild", e1);
        } catch (IOException e1) {
            Trace.log(Trace.MODULE_COMMON, Trace.LEVEL_INFO, " send data faild ");
            throw new BaseException("send data faild", e1);
        } finally {
            if (inputStream != null) {
                inputStream.close();
                Trace.log(Trace.MODULE_COMMON, Trace.LEVEL_INFO, " close inputStream success ");
            }
            if (outputStream != null) {
                outputStream.close();
                Trace.log(Trace.MODULE_COMMON, Trace.LEVEL_INFO, " close outputStream success ");
            }
            if (socket != null) {
                socket.close();
                Trace.log(Trace.MODULE_COMMON, Trace.LEVEL_INFO, " close socket success ");
            }

        }
        String resStr = sb.toString();
        resStr = Xml2JsonUtil.removeXmlNs(resStr);
        Trace.log("TCP", Trace.LEVEL_INFO, "TCP repsone :" + resStr);
        String jsonStr = Xml2JsonUtil.xml2Json("request", resStr);
        String backJsonStr = HeaderToBodyUtil.headerToBody(jsonStr);
        Trace.log(Trace.MODULE_COMMON, Trace.LEVEL_INFO, "response json is {}", backJsonStr);

        /*
        
        resStr =  JSONObject.fromObject(map).toString();*/

        return convertToStandardResponse(backJsonStr, "jh_common_receive");
    }

    /**
     * 转换网关的标准响应报文
     * 
     * @param jsonStr
     */
    private String convertToStandardResponse(String jsonStr, String beanName) {
        // 网关报文map
        Map<String, Object> gateWayMap = new HashMap<>();
        MessageDefine messageDefine = (MessageDefine)SpringContextsUtil.getBean(beanName);
        Map<String, Object> respMap = (Map<String, Object>)JSONObject.fromObject(jsonStr);
        Map<String, String> respHeaderMap = (Map<String, String>)respMap.get("responseHeader");

        Map<String, DataElement> standardMap = messageDefine.getElementMap();
        for (String standardKey : standardMap.keySet()) {
            if (respHeaderMap.containsKey(standardKey)) {
                respHeaderMap.put(((MsgField)(standardMap.get(standardKey))).getRefName(),
                    respHeaderMap.get(standardKey));
                respHeaderMap.remove(standardKey);
            }
        }

        gateWayMap.put(AdapterCanstants.HEADER, respHeaderMap);
        gateWayMap.put(AdapterCanstants.BODY, respMap.get("responseBody"));
        return JSONObject.fromObject(gateWayMap).toString();
    }

    @Override
    public void initConnector() {

    }

    @Override
    public String getIp() {
        return super.getIp();
    }

    @Override
    public void setIp(String ip) {
        super.setIp(ip);
    }

    @Override
    public String getPort() {
        return super.getPort();
    }

    @Override
    public void setPort(String port) {
        super.setPort(port);
    }

    @Override
    public String getUsname() {
        return super.getUsname();
    }

    @Override
    public void setUsname(String usname) {
        super.setUsname(usname);
    }

    @Override
    public String getPasswd() {
        return super.getPasswd();
    }

    @Override
    public void setPasswd(String passwd) {
        super.setPasswd(passwd);
    }

    @Override
    public IFormatter getRequestFormatter() {
        return super.getRequestFormatter();
    }

    @Override
    public void setRequestFormatter(IFormatter requestFormatter) {
        super.setRequestFormatter(requestFormatter);
    }

    @Override
    public IFormatter getResponseFormatter() {
        return super.getResponseFormatter();
    }

    @Override
    public void setResponseFormatter(IFormatter responseFormatter) {
        super.setResponseFormatter(responseFormatter);
    }

}
